package com.jolink.omiis.wechat.redis;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.msgpack.MessagePack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPubSub;

/**
 * 集群模式的Redis操作
 * 
 * @author WangYanqing
 *
 */
public class RedisClusterProcessor extends AbstractRedisProcessor implements IRedisProcessor {
	private static final Logger logger = LoggerFactory.getLogger(RedisClusterProcessor.class);

	@Override
	public Map<String, String> hgetall(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Map<String, String> value = jedis.hgetAll(key);
		if (value == null || value.isEmpty()) {
			logger.info("获取Rredis数据失败，再试一次。");
			value = jedis.hgetAll(key);
		}
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-getall操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return value;
	}

	@Override
	public String hmset(String key, Map<String, String> row) throws Exception {
		// TODO
		long t1 = System.currentTimeMillis();
		if (key.startsWith("S_") && key.endsWith("cXUg8tDY")) {
			throw new RuntimeException("终于找到你了！");
		}
		JedisCluster jedis = getJedisCluster();
		String statusCode = jedis.hmset(key, row);
		long t2 = System.currentTimeMillis();
		if (logger.isDebugEnabled()) {
			logger.debug("执行Redis-hmset操作成功，Key：{}，Row:{}，耗时：{}毫秒。", key, row, (t2 - t1));
		}
		return statusCode;
	}

	@Override
	public String hset(String key, String field, String value) throws Exception {
		Map<String, String> row = new HashMap<>();
		row.put(field, value);
		return hmset(key, row);
	}

	@Override
	public boolean exists(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Boolean flag = jedis.exists(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-exists操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return flag.booleanValue();
	}

	@Override
	public String expireKey(String key, int seconds) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long statusCode = jedis.expire(key, seconds);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-expireKey操作成功，Key：{}，Seconds：{}，耗时：{}毫秒。", key, seconds, (t2 - t1));
		return String.valueOf(statusCode);
	}

	@Override
	public String set(String key, String value) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		// Long statusCode = jedis.append(key, value);
		String statusCode = jedis.set(key, value);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-set操作成功，Key：{}，Value：{}，耗时：{}毫秒。", key, value, (t2 - t1));
		return statusCode;
	}

	@Override
	public String get(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		String value = jedis.get(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-get操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return value;
	}

	@Override
	public List<String> blpop(int timeout, String... keys) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		List<String> values = jedis.blpop(timeout, keys);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-blpop操作成功，Timeout：{}，Values：{}，耗时：{}毫秒。", timeout, Arrays.toString(keys), (t2 - t1));
		return values;
	}

	@Override
	public List<String> brpop(int timeout, String... keys) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		List<String> values = jedis.brpop(timeout, keys);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-brpop操作成功，Timeout：{}，Values：{}，耗时：{}毫秒。", timeout, Arrays.toString(keys), (t2 - t1));
		return values;
	}

	@Override
	public String rpop(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		String value = jedis.rpop(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-rpop操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return value;
	}

	@Override
	public String lpop(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		String value = jedis.lpop(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-lpop操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return value;
	}

	@Override
	public String llen(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long len = jedis.llen(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-llen操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return String.valueOf(len);
	}

	@Override
	public String lpush(String key, String... values) {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long statusCode = jedis.lpush(key, values);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-lpush操作成功，Key：{}，Values:{}，耗时：{}毫秒。", key, Arrays.toString(values), (t2 - t1));
		return String.valueOf(statusCode);
	}

	@Override
	public String lpush(String key, List<String> values) throws Exception {
		return lpush(key, values.toArray(new String[] {}));
	}

	@Override
	public String rpush(String key, String... values) {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long statusCode = jedis.rpush(key, values);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-rpush操作成功，Key：{}，Values：{}，耗时：{}毫秒。", key, Arrays.toString(values), (t2 - t1));
		return String.valueOf(statusCode);
	}

	@Override
	public String sadd(String key, String... values) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long statusCode = jedis.sadd(key, values);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-rpush操作成功，Key：{}，Values：{}，耗时：{}毫秒。", key, Arrays.toString(values), (t2 - t1));
		return String.valueOf(statusCode);
	}

	@Override
	public String scard(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long statusCode = jedis.scard(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-scard操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return String.valueOf(statusCode);
	}

	@Override
	public Set<String> smembers(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Set<String> set = jedis.smembers(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-smember操作成功，key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return set;
	}

	@Override
	public String spop(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		String value = jedis.spop(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-spop操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return value;
	}

	@Override
	public String zadd(String key, Map<String, Double> values) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long statusCode = jedis.zadd(key, values);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-zadd操作成功，Key：{}，Values：{}，耗时：{}毫秒。", key, values, (t2 - t1));
		return String.valueOf(statusCode);
	}

	@Override
	public String zcard(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long len = jedis.zcard(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-zcard操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return String.valueOf(len);
	}

	@Override
	public <T> String set(String key, T bean) throws Exception {
		long t1 = System.currentTimeMillis();
		MessagePack mp = new MessagePack();
		mp.register(bean.getClass());
		byte[] contents = mp.write(bean);
		JedisCluster jedis = getJedisCluster();
		String statusCode = jedis.set(key.getBytes(), contents);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-set操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return statusCode;
	}

	@Override
	public <T> T get(String key, Class<T> type) throws Exception {
		long t1 = System.currentTimeMillis();
		MessagePack mp = new MessagePack();
		JedisCluster jedis = getJedisCluster();
		byte[] contents = jedis.get(key.getBytes());
		mp.register(type);
		T bean = mp.read(contents, type);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-get操作成功，耗时：" + (t2 - t1) + "毫秒。");
		return bean;
	}

	@Override
	public String[] keys(String keyPattern) throws Exception {
		throw new RuntimeException("RedisCluster模式不支持Keys操作！");
	}

	@Override
	public String lrem(String key, String value) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long result = jedis.lrem(key, 0, value);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-lrem操作成功，Key：{}，Value：{}，耗时：{}毫秒。", key, value, (t2 - t1));
		return String.valueOf(result);
	}

	@Override
	public String incr(String key) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long result = jedis.incr(key);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-incr操作成功，Key：{}，耗时：{}毫秒。", key, (t2 - t1));
		return String.valueOf(result);
	}

	@Override
	public String hdel(String key, String... fields) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long result = jedis.hdel(key, fields);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-hdel操作成功，Key：{}，Fields：{}耗时：{}毫秒。", key, Arrays.toString(fields), (t2 - t1));
		return String.valueOf(result);
	}

	@Override
	public String del(String... keys) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long result = jedis.del(keys);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-del操作成功，Keys：{}耗时：{}毫秒。", Arrays.toString(keys), (t2 - t1));
		return String.valueOf(result);
	}

	@Override
	public void subscribe(JedisPubSub listener, String... channels) throws Exception {
		// if (!isSubscribe) {
		JedisCluster jedis = getJedisCluster();
		jedis.subscribe(listener, channels);
		// isSubscribe = true;
		// }
	}

	@Override
	public String srem(String key, String... members) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long result = jedis.srem(key, members);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-srem操作，Key：{}，Members：{}，耗时：{}毫秒。", key, members, (t2 - t1));
		return String.valueOf(result);
	}

	@Override
	public String hmset(String key, String... fields) throws Exception {
		long t1 = System.currentTimeMillis();
		JedisCluster jedis = getJedisCluster();
		Long result = jedis.srem(key, fields);
		long t2 = System.currentTimeMillis();
		logger.info("执行Redis-hmset操作，Key：{}，Fields：{}，耗时：{}毫秒。", key, Arrays.toString(fields), (t2 - t1));
		return String.valueOf(result);
	}

}
